/*************************************************************************
 *
 *  Copyright (C) 2013 Florian Dang <florian.coin@gmail.com>
 *
 *  This file is part of NatusVerse.
 *
 *  NatusVerse is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  NatusVerse is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with NatusVerse.  If not, see <http://www.gnu.org/licenses/>.
 *
 *************************************************************************/


#include "perfs.h"

#include <sys/time.h>
#include <iostream>
#include <string>


#include "utils.h"


double	perfs::my_gettimeofday()
{
	struct timeval tmp_time;
	gettimeofday(&tmp_time, NULL);

	return tmp_time.tv_sec + (tmp_time.tv_usec * 1.0e-6L);
}

double perfs::dotprodFLOP(unsigned int size)
{
	return 2 * size - 1.;
}

double perfs::mvFLOP(unsigned int rows, unsigned int columns)
{
	return rows * dotprodFLOP(columns);
}

double perfs::axpyFLOP(unsigned int size)
{
	return size * 2;
}

double perfs::scalFLOP(unsigned int size)
{
	return size;
}

double perfs::norm2FLOP(unsigned int size)
{
	return dotprodFLOP(size) + 1;
}

double perfs::mmFLOP(unsigned int size)
{
	return  dotprodFLOP(size) * size * size;
}

double perfs::gaussFLOP(unsigned int size)
{
	return  2 * size * size * size / 3;
}

double perfs::axpyPerf(unsigned int size, double time)
{
	return axpyFLOP(size) / time * 1.0e-9;
}

double perfs::mvPerf(unsigned int rows, unsigned int columns, double time)
{
	return mvFLOP(rows,columns) / time * 1.0e-9;
}

double perfs::mmPerf(unsigned int size, double time)
{
	if (time <= 0.0)
		return 0.0;

	return mmFLOP(size) / time * 1.0e-9;
}

double perfs::gaussPerf(unsigned int size, double time)
{
	int num_it = 300;

	#ifdef EXTERN_LOOP
		num_it *= 300 * 20;
	#endif

	return num_it * gaussFLOP(size) / time * 1.0e-9;
}

void perfs::Display(std::string s_method, double time, double flops)
{
	std::cout << "\\_o< Time " << s_method << " : " << time << " s" << std::endl;
	std::cout << "\\_o< Perf " << s_method << " : " << flops << " GFlops" << std::endl << std::endl;
}
